﻿#ifndef _RTMP_CHUNK_H
#define _RTMP_CHUNK_H

#include "rtmpMessage.h"

#include <QByteArray>
#include <QMap>

void WriteUint32BE(char* p, uint32_t value);
void WriteUint32LE(char* p, uint32_t value);
uint32_t ReadUint32BE(char* data);
uint32_t ReadUint32LE(char* data);
uint32_t ReadUint24BE(char* data);
uint32_t ReadUint24LE(char* data);
void WriteUint24BE(char* p, uint32_t value);
void WriteUint24LE(char* p, uint32_t value);
uint16_t ReadUint16BE(char* data);
uint16_t ReadUint16LE(char* data);
void WriteUint16BE(char* p, uint16_t value);
void WriteUint16LE(char* p, uint16_t value);

class RtmpHandshake
{
public:
    enum State
    {
        HANDSHAKE_C0C1,
        HANDSHAKE_S0S1S2,
        HANDSHAKE_C2,
        HANDSHAKE_COMPLETE
    };

    RtmpHandshake(State state=RtmpHandshake::HANDSHAKE_C0C1);
    virtual ~RtmpHandshake();

    int Parse(QByteArray& in_buffer, QByteArray& res_buf);

    int BuildC0C1(char* buf, uint32_t buf_size);

    bool IsCompleted() const
    {
        return handshake_state_ == HANDSHAKE_COMPLETE;
    }

private:
    State handshake_state_;
};

class RtmpChunk
{
public:
    enum State
    {
        PARSE_HEADER,
        PARSE_BODY,
    };

    RtmpChunk();
    virtual ~RtmpChunk();

    int Parse(QByteArray& in_buffer, RtmpMessage& out_rtmp_msg);

    int CreateChunk(uint32_t csid, RtmpMessage& rtmp_msg, char* buf, uint32_t buf_size);

    void SetInChunkSize(uint32_t in_chunk_size)
    { in_chunk_size_ = in_chunk_size; }

    void SetOutChunkSize(uint32_t out_chunk_size)
    { out_chunk_size_ = out_chunk_size; }

    void Clear()
    { rtmp_messages_.clear(); }

    int GetStreamId() const
    { return stream_id_; }

private:
    int ParseChunkHeader(QByteArray& buffer);
    int ParseChunkBody(QByteArray& buffer);
    int CreateBasicHeader(uint8_t fmt, uint32_t csid, char* buf);
    int CreateMessageHeader(uint8_t fmt, RtmpMessage& rtmp_msg, char* buf);

    State state_;
    int chunk_stream_id_ = 0;
    int stream_id_ = 0;
    uint32_t in_chunk_size_ = 128;
    uint32_t out_chunk_size_ = 128;
    QMap<int, RtmpMessage> rtmp_messages_;

    const int kDefaultStreamId = 1;
    const int kChunkMessageHeaderLen[4] = { 11, 7, 3, 0 };
};

#endif // RTMPCHUNK_H
